#pragma once
#include <iostream>

template <typename T>
class vector
{
    typedef T *iterator;
    typedef const T *const_iterator;

public:
    vector() : _start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {}
    void push_back(const T &val)
    {
        if (_finish == _end_of_storage)
        {
            size_t len = size();
            size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
            T *tmp = new T[newcapacity];
            if (_start)
            {
                memcpy(tmp, _start, sizeof(T) * len);
                delete[] _start;
            }
            _finish = tmp + size();
            _start = tmp;
            _end_of_storage = _start + newcapacity;
        }
        *_finish = val;
        _finish++;
    }

    void pop_back()
    {
        if (empty())
        {
            return;
        }
        _finish--;
    }

    void insert(iterator pos, const T &val)
    {
        if (_finish == _end_of_storage)
        {
            size_t len = pos - _start;
            size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
            T *tmp = new T[newcapacity];
            if (_start)
            {
                memcpy(tmp, _start, sizeof(T) * len);
                delete[] _start;
            }
            _finish = tmp + size();
            _start = tmp;
            _end_of_storage = _start + newcapacity;
        }
        iterator end = _finish - 1;
        while (end >= pos)
        {
            *(end + 1) = *end;
            end--;
        }
        *pos = val;
        _finish++;
    }

    void erase(iterator pos)
    {
        while (pos < _finish - 1)
        {
            *pos = *(pos + 1);
            pos++;
        }
        _finish--;
    }

    iterator begin()
    {
        return _start;
    }

    iterator end()
    {
        return _finish;
    }

    T &operator[](size_t pos)
    {
        return _start[pos];
    }

    bool empty()
    {
        return _start == _finish;
    }
    size_t size()
    {
        return _finish - _start;
    }

    size_t capacity()
    {
        return _end_of_storage - _start;
    }

    void print()
    {
        for (size_t i = 0; i < size(); i++)
        {
            std::cout << _start[i] << " ";
        }
        std::cout << std::endl;
    }

private:
    iterator _start;
    iterator _finish;
    iterator _end_of_storage;
};